package com.xunwulian.web.controller.pay;

import com.alibaba.dubbo.config.annotation.Reference;
import com.xunwulian.api.iface.TransactionAPI;
import com.xunwulian.api.iface.UserAPI;
import com.xunwulian.base.constant.TransStatus;
import com.xunwulian.base.constant.TransType;
import com.xunwulian.base.entity.TransactionEntity;
import com.xunwulian.base.entity.User;
import com.xunwulian.base.param.WeixinParam;
import com.xunwulian.base.util.BeanUtil3;
import com.xunwulian.base.util.PageData;
import com.xunwulian.base.util.StringUtil;
import com.xunwulian.web.bean.WeixinCallback;
import com.xunwulian.web.bean.WeixinEntity;
import com.xunwulian.web.bean.ZfbCallback;
import com.xunwulian.web.bean.ZfbEntity;
import com.xunwulian.web.controller.BaseController;
import com.xunwulian.web.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2017/3/7.
 */
@Controller
@RequestMapping(value = "/myPay")
public class PayController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(PayController.class);

    @Reference
    private TransactionAPI transactionAPI;

    @Reference
    private UserAPI userAPI;

    // 菜单地址(权限用)
    String menuUrl = "myPay/index.do";

    // 微信工具
    private WeiXinUtil weiXinUtil = new WeiXinUtil();

    // 二维码工具
    private QRUtil qrUtil = new QRUtil();

    // json工具
    private BeanUtil3 beanUtil3 = new BeanUtil3();

    /**
     * @return
     */
    @RequestMapping(value = "/index")
    public ModelAndView index() {

        // 从session获取用户信息
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        User user = (User) session.getAttribute(Const.SESSION_USER);

        ModelAndView mv = this.getModelAndView();

        mv.addObject("userName", user.getUSERNAME());

        mv.setViewName("transaction/pay");

        return mv;
    }

    /**
     * @return
     */
    @RequestMapping(value = "/success")
    public String success() {
        return "transaction/success";
    }

    /**
     * 充值
     *
     * @param payType
     * @param title
     * @param fee
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/payByQRCode")
    public void payByQRCode(int payType, String title, double fee, HttpServletResponse response) throws Exception {
        // 从session获取用户信息
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        User user = (User) session.getAttribute(Const.SESSION_USER);

        ZfbUtil zfbUtil = new ZfbUtil();

        // 返回结果的字节流
        String result = null;
        // 交易的Entity
        TransactionEntity transactionEntity = null;

        // 如果订单描述不为空并且交易额比0大
        if (fee > 0) {

            String desc = "账号：" + user.getUSERNAME() + "充值[" + fee + "]元";

            if (TransType.WEIXIN_PAY.getType().equals(payType)) {
                WeixinEntity weixinEntity = new WeixinEntity(desc, (int) fee * 100, WeixinParam.BACK_URL);

                transactionEntity = new TransactionEntity(weixinEntity.out_trade_no,
                        TransType.WEIXIN_PAY.getType(),
                        TransStatus.UNPAID.getType(),
                        fee,
                        user.getUSER_ID());

                weixinEntity.code_url = weiXinUtil.payForCodeUrl(weixinEntity);
                result = beanUtil3.beanToJson(weixinEntity);

            } else if (TransType.ZFB_PAY.getType().equals(payType)) {

                ZfbEntity zfbEntity = new ZfbEntity(desc, fee);

                transactionEntity = new TransactionEntity(zfbEntity.outTradeNo,
                        TransType.ZFB_PAY.getType(),
                        TransStatus.UNPAID.getType(),
                        fee,
                        user.getUSER_ID());

                zfbEntity.code_url = zfbUtil.payForQRCode(zfbEntity);
                result = beanUtil3.beanToJson(zfbEntity);
            }

            // TODO 异常处理
            transactionAPI.createTransaction(transactionEntity);

            logger.info("result:" + result);

            if (result != null) {
                response.getWriter().write(result);
                response.getWriter().flush();
                response.getWriter().close();
            }
        }
    }

    /**
     * 手工充值
     *
     * @param userId
     * @param fee
     * @return
     * @throws Exception
     */
//    @Transactional
    @RequestMapping(value = "/payByAdmin")
    public Object payByAdmin(String userId, double fee) throws Exception {
        // 从session获取用户信息
        Subject currentAdmin = SecurityUtils.getSubject();
        Session session = currentAdmin.getSession();
        User admin = (User) session.getAttribute(Const.SESSION_USER);

        TransactionEntity transactionEntity = new TransactionEntity(StringUtil.createIdentity(32),
                TransType.HAND_PAY.getType(),
                TransStatus.UNPAID.getType(),
                fee,
                userId,
                admin.getUSER_ID());

        // TODO 异常处理
        transactionAPI.createTransaction(transactionEntity);
        userAPI.increaseBalance(userId, fee);

        User user = userAPI.getByUid(userId);
        Double balance = user.getBalance();

        logger.info("increase balance:" + balance);

        Map map = new HashMap<String, Object>();
        map.put("balance", balance);
        return AppUtil.returnObject(new PageData(), map);
    }

    /**
     * 二维码
     *
     * @param code_url
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/qr")
    public void qr(String code_url, HttpServletResponse response) throws Exception {
        if (StringUtils.isNotBlank(code_url)) {
            byte[] qrBytes = qrUtil.generateQR(code_url);

            if (qrBytes != null) {
                response.getOutputStream().write(qrBytes);
                response.getOutputStream().flush();
                response.getOutputStream().close();
            }
        }
    }

    /**
     * 查询状态
     *
     * @param recordm
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/queryStatus")
    public void queryStatus(String recordm, HttpServletResponse response) throws Exception {
        logger.info("queryStatus: " + recordm);

        TransactionEntity trans = transactionAPI.findByRecordm(recordm);

        if (trans != null) {
            // 返回0代表支付成功，1代表未支付或者支付失败
            response.getWriter().write(String.valueOf(trans.getStatus() == 0 ? 1 : 0));
            response.getWriter().flush();
            response.getWriter().close();
        }
    }

    /**
     * 支付回调
     *
     * @param request
     * @throws Exception
     */
    @RequestMapping(value = "/payCallback")
    public void payCallback(HttpServletRequest request) throws Exception {

        WeixinCallback weixinCallback = weiXinUtil.parseCallback(request);

        System.out.println(weixinCallback);

        // 交易成功
        if (weixinCallback.result_code) {

            TransactionEntity trans = transactionAPI.findByRecordm(weixinCallback.out_trade_no);

            // 判断数据库
            if (trans.getStatus() != TransStatus.SUCCESS.getType()) {
                // Todo 异常处理
                transactionAPI.updateTransStatus(weixinCallback.out_trade_no, TransStatus.SUCCESS.getType());

                // TODO 事务处理
                // 修改账户余额
                userAPI.increaseBalance(trans.getUserId(), Double.valueOf(weixinCallback.total_fee / 100));
                logger.info("increaseBalance, userId:[%s], total_fee: [%lf]", trans.getUserId(), Double.valueOf(weixinCallback.total_fee / 100));
            }

        } else {

            // Todo 异常处理
            transactionAPI.updateTransStatus(weixinCallback.out_trade_no, TransStatus.FAIL.getType());
        }
        logger.info("payCallback: [%s]", weixinCallback.toString());
    }

    /**
     * 支付回调
     *
     * @param request
     * @throws Exception
     */
    @RequestMapping(value = "/payCallback2")
    public void payCallback2(HttpServletRequest request) throws Exception {

        ZfbUtil zfbUtil = new ZfbUtil();
        ZfbCallback zfbCallback = zfbUtil.parseCallback(request);

        logger.info(beanUtil3.beanToJson(zfbCallback));

        // 交易成功
        if (zfbCallback.trade_status != null || zfbCallback.trade_status.equals(ZfbCallback.TRADE_STATUS_SUCCESS)) {

            TransactionEntity trans = transactionAPI.findByRecordm(zfbCallback.out_trade_no);

            // 判断数据库
            if (trans.getStatus() != TransStatus.SUCCESS.getType()) {
                // Todo 异常处理
                transactionAPI.updateTransStatus(zfbCallback.out_trade_no, TransStatus.SUCCESS.getType());

                // TODO 事务处理
                // 修改账户余额
                userAPI.increaseBalance(trans.getUserId(), Double.valueOf(zfbCallback.total_amount));
            }

        } else {

            // Todo 异常处理
            transactionAPI.updateTransStatus(zfbCallback.out_trade_no, TransStatus.FAIL.getType());
        }
    }

}
